#include <iostream>

using namespace std;

/**
 * @brief Rational
 * @author redfrogotr
 * @date 2022/3/13
 */
class Rational {
private:
    int num;    // 分子
    int deno;   // 分母

public:
    Rational(int num = 1, int deno = 1);
    void setNum(int num);   // 设置分子
    bool setDeno(int deno); // 设置分母
    void simple();          // 约分
    void print();
    Rational add(const Rational &ra);
    Rational mul(const Rational &ra);
    void sub(const Rational &ra, const Rational &rb);
    void div(const Rational &ra, const Rational &rb);
};

Rational::Rational(int num, int deno) {
    this->num = num;
    if (deno == 0) {
        cout << "Denominator in args cannot be ZERO, so 1 the default value is used!\n";
        this->deno = 1;
    } else {
        this->deno = deno;
    }
}

void Rational::setNum(int num) {
    this->num = num;
}

bool Rational::setDeno(int deno) {
    if (deno == 0) {
        return false;
    }
    this->deno = deno;
    return true;
}

void Rational::simple() {
    // 分子为0，不必约分
    if (num == 0) {
        return ;
    }
    // gcd
    int a = abs(num), b = abs(deno), r;
    do {
        r = a % b;
        a = b;
        b = r;
    } while (r != 0);
    
    num /= a;
    deno /= a;
}

void Rational::print() {
    if (num == 0) {
        cout << 0 << endl;
        return ;
    }
    this->simple();

    bool isPos = num > 0 ? true : false;
    isPos = deno > 0 ? isPos : !isPos;
    if (!isPos) {
        cout << '-';
    }
    if (deno == 1) {
        cout << abs(num) << endl;
    } else {
        cout << abs(num) << '/' << abs(deno) << endl;
    }
}

Rational Rational::add(const Rational &ra) {
    int deno = this->deno * ra.deno;
    int num = this->num * ra.deno + ra.num * this->deno;
    this->deno = deno;
    this->num = num;
    this->simple();
    return *this;
}

Rational Rational::mul(const Rational &ra) {
    this->deno *= ra.deno;
    this->num *= ra.num;
    this->simple();
    return *this;
}

void Rational::sub(const Rational &ra, const Rational &rb) {
    int deno = ra.deno * rb.deno;
    int num = ra.num * rb.deno - rb.num * ra.deno;
    this->deno = deno;
    this->num = num;
    this->simple();
}

void Rational::div(const Rational &ra, const Rational &rb) {
    if (rb.num == 0) {
        cout << "the DIV process exited due to Rational B is ZERO!\n";
        this->num = 0;
        return ;
    }
    int deno = ra.deno * rb.num;
    int num = ra.num * rb.deno;
    this->deno = deno;
    this->num = num;
    this->simple();
}

int main() {
    Rational r;
    int num, deno;
    // input 1st rational, inilializing by setter
    cout << "YOU can input NUMerator and DENOminator of Rational: " << endl;
    cin >> num >> deno;
    r.setNum(num);
    r.setDeno(deno);
    r.print();
    // input 2nd rational, initializing by constructor
    cout << "YOU can input NUMerator and DENOminator of 2nd Rational: " << endl;
    cin >> num >> deno;
    Rational r2(num, deno);
    r2.print();

    Rational tr = r, tr2 = r2;
    cout << "+ ";
    tr.add(tr2).print();
    cout << "- ";
    tr.sub(r, r2);
    tr.print();
    cout << "* ";
    tr = r;
    tr.mul(tr2).print();
    cout << "/ ";
    tr.div(r, r2);
    tr.print();

    return 0;
}
